home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 088 (1990-11)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 088 (1990-11)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / du / du.c < prev    next >
C/C++ Source or Header  |  1990-11-14  |  9KB  |  332 lines

  1. ; /* To make, just execute me
  2. lc -v -j73 -j104 -O -cusf -M du
  3. blink du.o lib lib:lcr.lib nd sc sd batch quiet 
  4. protect du +p
  5. quit
  6. ;lcr.lib there for long division routine only
  7. */
  8. /************************************************************************
  9.  * du.c -- calculate disk usage for files in a directory tree        *
  10.  *                                    *
  11.  *        Copyright 1989,1990 Peter Chubb                *
  12.  *           All rights reserved                    *
  13.  *                                    *
  14.  ************************************************************************/
  15.  
  16. static const char RCSid[] = "$Id: du.c,v 1.4 90/08/08 20:51:48 peterc Exp $";
  17.  
  18. /*
  19.  * Written:
  20.  *    10 July 1989 Peter Chubb
  21.  *
  22.  *  This is not guaranteed to work with any file systems other than the
  23.  *  old (Slow) file system,. and the new (Fast) file system, as it
  24.  *  contains code that `understands' the shape of these two filesystems.
  25.  *
  26.  * $Log:    du.c,v $
  27.  * Revision 1.4  90/08/08  20:51:48  peterc
  28.  * Moved knowledge about filesystems into table.
  29.  * Added const keyword where appropriate to try to give optimiser some hints.
  30.  * Moved constant repeated strings into named variables to try to
  31.  * save some space.
  32.  * 
  33.  * Revision 1.3  90/06/11  11:10:11  peterc
  34.  * Added ability to cope with quoted filenames.
  35.  * Also fixed large file bug.
  36.  * 
  37.  * Revision 1.2  90/06/06  20:07:37  peterc
  38.  * Added options to allow selection of blocksize;
  39.  * added allowance for file extension blocks.
  40.  * 
  41.  *
  42.  */
  43.  
  44. #include <libraries/dos.h>
  45. #include <proto/dos.h>
  46. #include <proto/exec.h>
  47. #include <exec/memory.h>
  48. #include <string.h>
  49. #include <stdlib.h>
  50. #include <dos.h>
  51.  
  52. #ifndef min
  53. #    define min(a, b) ((a) < (b) ? (a) : (b))
  54. #endif
  55.  
  56. #define ABSEXECBASE ((struct ExecBase **)4L)
  57. typedef unsigned short ushort;
  58.  
  59. void RawDoFmt(const char *fmt, const void *arglist, void (*prbuf)(), char *obuf);
  60. #pragma syscall RawDoFmt 20a ba9804
  61.  
  62. void __asm prbuf(const register __d0 char c);
  63. #define R_A3 (8+3)
  64.  
  65. struct DosLibrary *DOSBase;
  66.  
  67. void outval(const char *fmt,...);
  68.  
  69. long __regargs du(const BPTR dir, const long verbosity, 
  70.           const unsigned long level, const 
  71.           struct fsdesc *fp);
  72.  
  73. long __asm __saveds dumain(register __a0 char *cmd);
  74. unsigned long __regargs numBlocks(const LONG size, const struct fsdesc *fp);
  75.  
  76. #define SFS    0
  77. #define FFS    1
  78.  
  79. #define    SECSIZE    512
  80.  
  81. const char spaces[] = "                                ";
  82. const char fmt[]    = "%-32ls    %6ld\n";
  83.  
  84. const struct fsdesc
  85. {
  86.     const char    fs_tnam;    /* flag to choose this fstype */
  87.     const ushort    fs_dbytes;    /* bytes per data block */
  88.     const ushort    fs_fxdovhd;    /* fixed per-file overhead */
  89.     const ushort    fs_varovhd;    /* extra block for every fs_varovhd blocks */
  90. } fstab[] =    /* real file systems should be before fake ones such as tar */
  91. {
  92.     {        /* Slow file system */
  93.     'S',
  94.     SECSIZE - (6 * sizeof(long)),    /* data block has 6 long header */
  95.     1,                /* at least one header block    */
  96.     SECSIZE/sizeof(long) - 56,    /* and a block full of pointers, with a 56 long header */
  97.     },
  98.     {        /* Fast file system */
  99.     'F',
  100.     SECSIZE,            /* no header in data block */
  101.     1,                /* at least one header block */
  102.     SECSIZE/sizeof(long) - 56    /* block full of pointers, 56 long header */
  103.     },
  104.     {        /* posix tar archive */
  105.     'T',
  106.     SECSIZE,
  107.     1,
  108.     0
  109.     },
  110. };
  111.  
  112. #define NFILESYS    (sizeof(fstab) / sizeof(fstab[0]))
  113.  
  114. /* main routine -- parse arguments, then call du() to do the work */
  115. long __asm __saveds
  116. dumain(register __a0 char *cmd)
  117. {
  118.     const struct fsdesc     *fp = (struct fsdesc *) 0;
  119.     register char     *p;
  120.     long             c;
  121.     long           total;
  122.     long            verbosity = 1;
  123.     BPTR            dir;
  124.     struct Library      *foo;
  125.     struct InfoData       infodata;
  126.  
  127.     if (!(foo = OpenLibrary("dos.library", 0)))
  128.         return RETURN_ERROR;
  129.     DOSBase = (struct DosLibrary *) foo;
  130.  
  131.     while ((c = *cmd++) == ' ' || c == '    ')
  132.     ;
  133.  
  134.     while ((char)c == '-')
  135.     {
  136.         c = *cmd++;
  137.     switch((char)c)
  138.     {
  139.     case 's':    
  140.         verbosity = 0;
  141.         break;
  142.  
  143.     case 'v':
  144.         verbosity++;
  145.         break;
  146.  
  147.     default:
  148.         if (fp) {
  149.         outval ("File system blocksize specified twice!\n");
  150.         goto out;
  151.         }
  152.         for (fp = &fstab[0]; fp < &fstab[NFILESYS]; fp++) {
  153.         if (fp->fs_tnam == (char)c)
  154.             break;
  155.         }
  156.         if (!fp) {
  157.         outval("Usage: du [-s | -v] [-F | -S | -T] [dirname]\n");
  158.         goto out;
  159.         }
  160.         break;
  161.     }
  162.     while ((c = *cmd++) == ' ')
  163.         ;
  164.     } 
  165.     p = --cmd;
  166.     if (*p == '\"')
  167.     {
  168.     ++cmd;
  169.     while (*p && *p != '\n' && *++p != '\"')
  170.         ;
  171.     }
  172.     else
  173.     while (*p && *p != ' ' && *p != '\n')
  174.         p++;
  175.     *p = '\0';
  176.  
  177.     if (p != cmd) {
  178.     c = 1;
  179.     dir = Lock(cmd, ACCESS_READ);
  180.     } else {
  181.     c = 0;
  182.     (void) CurrentDir(dir = CurrentDir(0L));
  183.     }
  184.     if (!dir) {
  185.         outval("Can't open %ls\n", cmd);
  186.     return RETURN_WARN;
  187.     }
  188.  
  189.     if (!fp) {
  190.     Info(dir, &infodata);
  191.     for (fp = fstab; fp < &fstab[NFILESYS]; fp++)
  192.         if (fp->fs_dbytes == infodata.id_BytesPerBlock)
  193.         break;
  194.         if (fp == &fstab[NFILESYS]) {
  195.         outval("du: unknown filesystem type, blocksize %d\n", infodata.id_BytesPerBlock);
  196.         goto out;
  197.     }
  198.     }
  199.  
  200.     total = du(dir, verbosity, 0, fp);
  201.  
  202.  
  203.     if (total >= 0)
  204.         outval("Total: %ld\n", total);
  205.     else
  206.     outval("**BREAK**\n\n");
  207. out:
  208.     if (c == 1)
  209.     UnLock(dir);
  210.  
  211.     CloseLibrary(foo);
  212.     return RETURN_OK;
  213. }
  214.  
  215.  
  216. /* outval -- our equivalent of printf */
  217. void
  218. outval(const char *fmt, ...)
  219. {
  220.     char obuf[200];
  221.    
  222.     RawDoFmt(fmt, (&fmt) + 1, prbuf, obuf);
  223.     Write(Output(), obuf, strlen(obuf));
  224. }
  225.  
  226. /* du -- calculate and print disc usage */
  227. long __regargs
  228. du(dir, verbosity, level, fp)
  229. const BPTR    dir; /* lock on top of directory tree */
  230. const long     verbosity; /* whether to print or not */
  231. const unsigned long level; /* how deep in the tree */
  232. const struct fsdesc *fp;
  233. {
  234.     /* note all these are longword aligned */
  235.  
  236.     struct FileInfoBlock fib;
  237.     BPTR       lck;
  238.     long    total = 0;
  239.     long    extra;
  240.     BPTR       curdir = CurrentDir(dir);
  241.     long    abort = 0;
  242.  
  243.     if (Examine(dir, &fib)) {
  244.     if (fib.fib_DirEntryType < 0) { /* 
  245.                      * must be the only file specified
  246.                      *  -- always print 
  247.                      */
  248.         Write(Output(), spaces, (long)min(level, sizeof(spaces)));
  249.             outval(fmt, fib.fib_FileName, 
  250.                 total = numBlocks(fib.fib_Size, fp));
  251.     } else {
  252.         total++; /* for directory block itself */
  253.         while (ExNext(dir, &fib) && abort >= 0) {
  254.             if (SetSignal(0, 0) & SIGBREAKF_CTRL_C)
  255.             abort = -1;
  256.             else {
  257.             extra = numBlocks(fib.fib_Size, fp);
  258.                 if (fib.fib_DirEntryType > 0) {
  259.             lck = Lock(fib.fib_FileName, ACCESS_READ);
  260.             /* should really check that lock succeeded... */
  261.             extra += (abort = du(lck, verbosity, level+1, fp));
  262.                 UnLock(lck);
  263.             }
  264.             total += extra;
  265.             switch (verbosity) {
  266.             case 0: /* -s option */
  267.                 break;
  268.  
  269.             case 1: /* default -- print iff directory */
  270.                 if (fib.fib_DirEntryType < 0)
  271.                 break;
  272.             /* FALL THROUGH */
  273.  
  274.             default: /* verbose -- always print */
  275.             Write(Output(), spaces, (long) min(level, (sizeof spaces)));
  276.                     outval(fmt, fib.fib_FileName, extra);
  277.                 }
  278.                 }
  279.             }
  280.     }
  281.     }
  282.     (void) CurrentDir(curdir);
  283.     return abort < 0 ? -1 : total;
  284. }
  285.  
  286.  
  287.  
  288. /*----------------------------------------------------------------*/
  289. /* This stub routine is called from the RawDoFmt routine for each */
  290. /* character in the string.  At invocation, we have:              */
  291. /*   D0 - next character to be formatted                          */
  292. /*   A3 - pointer to data buffer                                  */
  293. /* Stolen from Lattice-supplied Avail utility              */
  294. /*----------------------------------------------------------------*/
  295. void __asm prbuf(const register __d0 char c)
  296. {
  297.     char *p = (char *)__builtin_getreg(R_A3);
  298.     *p++ = c;
  299.     __builtin_putreg(R_A3, (long)p);
  300.  
  301.     /* It's a pity this doesn't generate
  302.      *      move.b d0,(a3)+
  303.      *   rts
  304.      */
  305. }
  306.  
  307. /* numBlocks -- work out how many blocks a file takes */
  308. unsigned long __regargs
  309. numBlocks(const LONG size, const struct fsdesc *fp)
  310. {
  311.     register unsigned long blocks;
  312.     /*
  313.      * A data block holds fp->fs_dbytes bytes.
  314.       * Files also have extension blocks,
  315.      * and at least one header block.
  316.      * Each header block contains some amount of header info, 
  317.      * and the remainder is filled with longs, each of which can
  318.      * address one block.  The number of longs is held as fp->fs_varovhd.
  319.      *
  320.      * The algorithm used is less efficient than it could be,
  321.      * but who cares: the disc access time swamps it.
  322.      */
  323.  
  324.     /* number of data blocks + fixed file overhead */
  325.     blocks = ((size + fp->fs_dbytes - 1) / fp->fs_dbytes) + fp->fs_fxdovhd;;
  326.     /* add in header blocks */
  327.     if (fp->fs_varovhd)
  328.         blocks += (blocks / fp->fs_varovhd);
  329.  
  330.     return blocks;
  331. }
  332.